

#include "resourcemanager.h"

#include "strutil.h"
#include "unit.h"
#include "animation.h"
#include "gamemanager.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#import <Foundation/Foundation.h>
#endif

#define a2f(s)				static_cast<float>(atof(s))

const string RES_PATH = "textures/";
const char* DEFAULT_TEXTURE_NAME = "textures/default.png";

ResourceManager* ResourceManager::_instance = nullptr;


ResourceManager::ResourceManager() {
}

ResourceManager::~ResourceManager() {
}

ResourceManager* ResourceManager::getInstance(){
	if(_instance == nullptr){
		_instance = new ResourceManager();
	}

	return _instance;
}

void ResourceManager::init() {
	loadAnimationData();
	loadStrings();
}


string ResourceManager::loadTextFile(const string& fileName) {
	unsigned long length;
	char* str = (char*)FileUtils::getInstance()->getFileData(fileName.c_str(), "rb", &length);
	string s = str;
	delete[] str;
	return s;
}


const char* ResourceManager::getStringValue(const char* key) {
	auto it = mapStrings.find(key);
	return it == mapStrings.end() ? key : it->second.c_str();
}

Sprite *ResourceManager::createSprite(const string& name) {
	Sprite *spr = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(name.c_str()));
	if(!spr) {
		spr = Sprite::create(name.c_str());
	}

	if(!spr) {
		log("texture not found: %s", name.c_str());
		spr = Sprite::create(DEFAULT_TEXTURE_NAME);
	}

	spr->setScale(GM->minscale);

	return spr;
}

SpriteFrame *ResourceManager::createSpriteFrame(const string& name) {
	SpriteFrame *f = SpriteFrameCache::getInstance()->getSpriteFrameByName(name.c_str());
	if(!f) {
		Sprite *spr = Sprite::create(name.c_str());
		if(spr) {
			f = spr->displayFrame();
		}
	}

	if(!f) {
		log("texture not found: %s", name.c_str());
		Sprite *spr = Sprite::create(DEFAULT_TEXTURE_NAME);
		f = spr->displayFrame();
	}

	return f;
}

FrameAnimation * ResourceManager::createAnimation(const string& animKey, const Point& location) {
	AnimationInfo info = animationInfos[animKey];

	FrameAnimation * anim = new FrameAnimation();
	anim->init();
	anim->set(info.key, info.frameRate, info.frames);
	anim->setScale(GM->minscale);
	anim->setLogicPosition(location);
	anim->autorelease();

	return anim;
}

MenuItemSprite *ResourceManager::createButton(const char* spriteName, ccMenuCallback func, Node *parent) {
	char buf[100];
	sprintf(buf, "%s_0.png", spriteName);
	Sprite *s1 = createSprite(buf);
	sprintf(buf, "%s_1.png", spriteName);
	Sprite *s2 = createSprite(buf);
	sprintf(buf, "%s_2.png", spriteName);
	Sprite *s3 = createSprite(buf);

	MenuItemSprite *button = MenuItemSprite::create(s1, s2, s3, func);
	button->setScale(GM->minscale);

	/*Menu *menu = Menu::create(button, nullptr);
	menu->setPosition(Point::ZERO);
	if (parent) {
	parent->addChild(menu);
	}*/

	if(parent) {
		parent->addChild(button);
	}

	return button;
}

void ResourceManager::loadStrings(const char* locale) {
	using namespace tinyxml2;
	tinyxml2::XMLDocument doc;

	char buf[100];
	sprintf(buf, "data/strings/%s/strings.xml", locale);
	string content = loadTextFile(buf);
	doc.Parse(content.c_str());

	XMLElement* pData = doc.FirstChildElement("data");
	XMLElement* pItem = pData->FirstChildElement("i");
	while (pItem) {
		string name = pItem->Attribute("k");
		string value = "";
		const char* s = pItem->GetText();
		if(s) {
			value = s;
		}
		mapStrings.insert(make_pair(name, value));
		pItem = pItem ->NextSiblingElement("i");
	}
}

void ResourceManager::loadAnimationData() {
	using namespace tinyxml2;

	string xml = ResourceManager::loadTextFile("data/animations.xml");

	tinyxml2::XMLDocument doc;
	doc.Parse(xml.c_str());

	XMLElement* root = doc.FirstChildElement("data");
	XMLElement* item = root->FirstChildElement("i");
	while(item){
		AnimationInfo info;
		info.key = item->Attribute("k");
		info.frameRate = item->IntAttribute("frame_rate") / 1000.0f;

		XMLElement* xeFrames = item->FirstChildElement("f");
		while(xeFrames) {
			info.frames.push_back(xeFrames->GetText());
			xeFrames = xeFrames->NextSiblingElement("f");
		}

		animationInfos.insert(make_pair(info.key, info));

		item = item->NextSiblingElement("i");
	}
}

void ResourceManager::createBackground( Node* parent, const char* textureName )
{
	Sprite *spr = Sprite::create(textureName);
	spr->setAnchorPoint(Point::ZERO);

	Size size = spr->getContentSize();
	Size parentSize = parent->getContentSize();

	spr->setScaleX(parentSize.width / size.width);
	spr->setScaleY(parentSize.height / size.height);

	parent->addChild(spr);
}

LabelTTF* ResourceManager::createButtonLabelTTF(const char* text, Node* parent, int fontSize) {
	Size parentSize = parent->getContentSize();

	LabelTTF* label = LabelTTF::create(text, "", fontSize);
	label->setPosition(Point(parentSize.width / 2.0f, parentSize.height / 2.0f));

	parent->addChild(label);

	return label;
}

LabelBMFont* ResourceManager::createButtonLabelBMFont(const char* text, Node* parent, const char* fontName) {
	Size parentSize = parent->getContentSize();

	LabelBMFont* label = LabelBMFont::create(text, fontName);
	label->setPosition(Point(parentSize.width / 2.0f, parentSize.height / 2.0f));

	parent->addChild(label);

	return label;
}
